<?php
/**
 * NetBiz Framework
 * Copyright (C) 20009 - 2010 NetBiz
 * 
 * All rights reserved.
 */

class FRM_Pager_RangeIterator implements FRM_Pager_IteratorInterface
{
	protected $_range = array();

	protected $_current = NULL;
	protected $_first = NULL;
	protected $_last = NULL;
	protected $_page = NULL;
	protected $_count = NULL;


	function __construct()
	{
		// We use func_get_args
		// () -> standard iterator, full range
		// ($current) ->  $page centered iterator, with $current length
		// ($first, $current) -> ($first, $current, $first)
		// ($first, $current, $last) -> $page centered iterator, with an initial
		//	length of first, and middle length of $current, and a final length of $last
		$num_args = func_num_args();
		$args = func_get_args();

		switch($num_args)
		{
			case 1 :
				$this->_current = $args[0];
			break;

			case 2 :
				$this->_first = $args[0];
				$this->_last = $this->_first;
				$this->_current = $args[1];
			break;

			case 3 :
				$this->_first = $args[0];
				$this->_current = $args[1];
				$this->_last = $args[2];
			break;

			default :
			break;
		}
	}


	/**
	 * implementing FRM_Pager_IteratorInterface
	 */

	/**
	 * @link FRM_Pager_IteratorInterface::initialize
	 */
	public function initialize($page,$count)
	{
		$this->_page = $page;
		$this->_count = $count;

		// Build ranges
		if ($this->_current)
		{
			if ($this->_first)
			{
				$this->_range = array_merge($this->_range,range(1,$this->_first));
			}

			$deltaMin = intval(($this->_current-1)/2);
			$deltaMinOffset = max(0,$deltaMin - $this->_page + 1);
			$deltaPlus = $this->_current - 1 - $deltaMin;
			$deltaPlusOffset = max(0,$deltaPlus - ($this->_count - $this->_page));
			$this->_range = array_merge($this->_range,range($this->_page - $deltaMin - $deltaPlusOffset,$this->_page + $deltaPlus + $deltaMinOffset));

			if ($this->_last)
			{
				$this->_range = array_merge($this->_range,range($this->_count + 1 - $this->_last,$this->_count));
			}

			$this->_range = array_unique($this->_range);
			sort($this->_range);

			// Normalize on 1, $count
			$pos_low = 0;
			$nb = count($this->_range);
			for(;$pos_low < $nb; ++ $pos_low)
			{
				if ($this->_range[$pos_low] >= 1)
				{
					break;
				}
			}

			$pos_high = $nb-1;
			for(;$pos_high >= 0; -- $pos_high)
			{
				if ($this->_range[$pos_high] <= $this->_count)
				{
					break;
				}
			}

			// Splice the array
			$this->_range = array_splice($this->_range,$pos_low,$pos_high+1-$pos_low);
		}
		else
		{
			$this->_range = range(1,$this->_count);
		}
	}

	/**
	 * Implementing Iterator
	 */
	private $_transient = FALSE;
	private $_valid_iter = TRUE;

	public function rewind()
	{
		reset($this->_range);
		$this->_transient = FALSE;
		$this->_valid_iter = TRUE;
	}
		
	public function current()
	{
		if ($this->_transient)
		{
			return FALSE;
		}
		else
		{
			return current($this->_range);
		}
	}
		
	public function key()
	{
		return key($this->_range);
	}
		
	public function next()
	{
		if ($this->_transient)
		{
			$this->_transient = FALSE;
		}
		else
		{
			$cur = current($this->_range);
			$n = next($this->_range);

			if ($n === FALSE)
			{
				$this->_valid_iter = FALSE;
				return FALSE;
			}
			elseif($n != $cur+1)
			{
				$this->_transient = TRUE;
			}

			return $cur;
		}
	}
		
	public function valid()
	{
		return $this->_valid_iter;
	}
}